package com.htstar.ovms.admin.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.htstar.ovms.admin.api.entity.SysFile;
import com.htstar.ovms.admin.mapper.SysFileMapper;
import com.htstar.ovms.admin.service.SysFileService;
import com.htstar.ovms.common.core.constant.CommonConstants;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.minio.service.MinioTemplate;
import com.htstar.ovms.common.security.util.SecurityUtils;
import io.minio.ObjectStat;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件管理
 *
 * @author Luckly
 * @date 2019-06-18 17:18:42
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService {
    private final MinioTemplate minioTemplate;

    /**
     *
     */

    public R uploadExcel(FileInputStream file, String fileName) {

        return R.ok();
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @Override
    public R uploadFile(MultipartFile file) {

        boolean m = this.checkFileSize(file.getSize(), 2, "M");
        if(!m){
            return  R.failed("文件大小不能超过2M");
        }
        String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
        Map<String, String> resultMap = new HashMap<>(4);
//		resultMap.put("bucketName", CommonConstants.BUCKET_NAME);
        resultMap.put("bucketName", "ovms");
        resultMap.put("fileName", fileName);
        resultMap.put("url", String.format("/admin/sys-file/%s/%s", CommonConstants.BUCKET_NAME, fileName));

        try {
            minioTemplate.putObject("ovms", fileName, file.getInputStream());
            //文件管理数据记录,收集管理追踪文件
            fileLog(file, fileName);
        } catch (Exception e) {
            log.error("上传失败", e);
            return R.failed(e.getLocalizedMessage());
        }
        return R.ok(resultMap);
    }

    /**
     * Description: 多文件上传
     * Author: flr
     * Date: 2020/7/16 11:56
     * Company: 航通星空
     * Modified By:
     */
    @Override
    public R uploadFiles(MultipartFile[] files) {
        List<Map<String, String>> list = new ArrayList<>();
        for (MultipartFile file : files) {
            R r = uploadFile(file);
            list.add((Map<String, String>) r.getData());
        }
        return R.ok(list);
    }

    /**
     * 文件上传
     *
     * @param bucketName
     * @param objectName
     * @param stream
     * @throws Exception
     */
    @Override
    public void uploadFileExl(String bucketName, String objectName, InputStream stream) throws Exception {
        minioTemplate.putObject(bucketName, objectName, stream);
        ;
    }

    /**
     * 文件获取
     *
     * @param bucket
     * @param fileName
     * @return
     * @throws Exception
     */
    @Override
    public ObjectStat getFileExl(String bucket, String fileName) throws Exception {
        return minioTemplate.getObjectInfo(bucket, fileName);
    }

    /**
     * 读取文件
     *
     * @param bucket
     * @param fileName
     * @param response
     */
    @Override
    public void getFile(String bucket, String fileName, HttpServletResponse response) {

//        try (InputStream inputStream = minioTemplate.getObject(bucket, fileName)) {
//            response.setContentType("application/octet-stream; charset=UTF-8");
//            IoUtil.copy(inputStream, response.getOutputStream());
//        } catch (Exception e) {
//            log.error("文件读取异常: {}", e.getLocalizedMessage());
//        }
        InputStream inputStream = null;
        try {
            inputStream = minioTemplate.getObject(bucket, fileName);
            response.setContentType("application/octet-stream; charset=UTF-8");
            IoUtil.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("文件读取异常: {}", e.getLocalizedMessage());
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除文件
     *
     * @param id
     * @return
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFile(Long id) {
        SysFile file = this.getById(id);
        minioTemplate.removeObject(CommonConstants.BUCKET_NAME, file.getFileName());
        return this.removeById(id);
    }


    /**
     * 文件管理数据记录,收集管理追踪文件
     *
     * @param file     上传文件格式
     * @param fileName 文件名
     */
    private void fileLog(MultipartFile file, String fileName) {
        SysFile sysFile = new SysFile();
        //原文件名
        String original = file.getOriginalFilename();
        sysFile.setFileName(fileName);
        sysFile.setOriginal(original);
        sysFile.setFileSize(file.getSize());
        sysFile.setType(FileUtil.extName(original));
        sysFile.setBucketName(CommonConstants.BUCKET_NAME);
        sysFile.setCreateUser(SecurityUtils.getUser().getUsername());
        this.save(sysFile);
    }
    /**
     * 判断文件大小
     *
     * @param len
     *            文件长度
     * @param size
     *            限制大小
     * @param unit
     *            限制单位（B,K,M,G）
     * @return
     */
    public  boolean checkFileSize(Long len, int size, String unit) {
//        long len = file.length();
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        if (fileSize > size) {
            return false;
        }
        return true;
    }
}
